// SelectionHandler.cpp: implementation of the CSelectionHandler class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ansiterminal.h"
#include "SelectionHandler.h"

#include "AnsiTerminalView.h"
#include "AnsiScreen.h"
#include "AnsiTerminalDoc.h"
#include "GlobalFuncs.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSelectionHandler::CSelectionHandler(CAnsiTerminalView *pView)
{
	m_pView = pView;
	m_bSelecting = FALSE;
	m_bSelected = FALSE;
	m_bCancelingSelection = FALSE;
}


BOOL CSelectionHandler::OnMouseDown(CPoint ptCell, UINT nFlags)
{
	m_ptDownCell = ptCell;
	if(m_bSelected)
	{
		CAnsiScreen &screen = m_pView->GetDocument()->GetScreen();
		BYTE **effects = screen.GetEffects();
		CSize sizeScr = screen.GetSize();
		for(int y = 0; y < sizeScr.cy; y++)
		{
			memset(effects[y], 0, sizeof(BYTE) * sizeScr.cx);
		}
// 		m_pView->Invalidate(FALSE);
// 		m_pView->UpdateWindow();
		m_pView->Refresh();
		
		m_bSelected = FALSE;
		m_bCancelingSelection = TRUE;
		return TRUE;
	}

	return FALSE;
}

BOOL CSelectionHandler::OnMouseMove(CPoint ptCell, UINT nFlags)
{
	if(nFlags & MK_LBUTTON)
	{
		if(m_bSelecting || ptCell != m_ptMoveCell)
		{
			m_ptMoveCell = ptCell;
			m_bSelecting = TRUE;
			m_bCancelingSelection = FALSE;
			UpdateSelection();
			return TRUE;
		}
	}
	if(m_bCancelingSelection || m_bSelected)
	{
		return TRUE;
	}	
	return FALSE;
}

BOOL CSelectionHandler::OnMouseUp(CPoint ptCell, UINT nFlags)
{
	if(m_bCancelingSelection)
	{
		m_bCancelingSelection = FALSE;
		return TRUE;
	}
	if(m_bSelecting)
	{
		m_bSelected = TRUE;
		m_bSelecting = FALSE;
		return TRUE;
	}
	return FALSE;
}

void CSelectionHandler::UpdateSelection()
{
	int x, y;
	CAnsiScreen &screen = m_pView->GetDocument()->GetScreen();
	BYTE **effects = screen.GetEffects();
	CSize sizeScr = screen.GetSize();
	for(y = 0; y < sizeScr.cy; y++)
	{
		memset(effects[y], 0, sizeof(BYTE) * sizeScr.cx);
	}
	CRect rectScr(0, 0, sizeScr.cx - 1, sizeScr.cy - 1);
	CPoint pt1(m_ptDownCell);
	CPoint pt2(m_ptMoveCell);
	GlobalFuncs::EnsurePtInRect(pt1, rectScr);
	GlobalFuncs::EnsurePtInRect(pt2, rectScr);
	
	BOOL blockSelect = GetAsyncKeyState(VK_MENU) < 0;
	if(blockSelect)
	{
		CRect rectBlock(pt1, pt2);
		rectBlock.NormalizeRect();
		for(y = rectBlock.top; y <= rectBlock.bottom; y++)
		{
			memset(effects[y] + rectBlock.left, EffectInverse, sizeof(BYTE) * rectBlock.Width() + 1);
		}
	}
	else
	{
		BOOL swapStEndPoint = (m_ptDownCell.y > m_ptMoveCell.y) || (m_ptDownCell.y == m_ptMoveCell.y && m_ptDownCell.x > m_ptMoveCell.x);
		if(swapStEndPoint)
		{
			swap(pt1, pt2);
		}
		
		for(y = pt1.y; y <= pt2.y; y++)
		{
			memset(effects[y], EffectInverse, sizeof(BYTE) * sizeScr.cx);
		}
		for(x = 0; x < pt1.x; x++)
		{
			effects[pt1.y][x] = EffectNone;
		}
		for(x = pt2.x + 1; x < sizeScr.cx; x++)
		{
			effects[pt2.y][x] = EffectNone;
		}
	}
// 	m_pView->Invalidate(FALSE);
// 	m_pView->UpdateWindow();
	m_pView->Refresh();
}

BOOL CSelectionHandler::OnMouseWheel(CPoint ptCell, UINT nFlags, short wheelNotches)
{
	return FALSE;
}

BOOL CSelectionHandler::IsSelected()
{
	return m_bSelected;
}

BOOL CSelectionHandler::OnFreezeMouse(BOOL bFreeze)
{
	return TRUE;
}